package asteroids.model;

import asteroids.Util;
import be.kuleuven.cs.som.annotate.*;

import java.lang.Math;

@Value
public class Vector {
	
	private final double x;
	private final double y;
	
	/**
	 * @param x
	 * @param y
	 */
	public Vector(double x, double y) {
		this.x = x;
		this.y = y;
	}

	
	/**
	 * Gives the x-co of this vector the given value
	 * @param x
	 * @post	the x-co of this vector is equal to the given x
	 * 			| this.getX() = x
	 */
	public void setX(double x) {
		//this.x = x;
	}
	
	@Basic
	public double getX() {
		return x;
	}
	
	/**
	 * Gives the y-co of this vector the given value
	 * @param y
	 * @post	the y-co of this vector is equal to the given y
	 * 			| this.getY() = y
	 */
	public void setY(double y) {
		//this.y = y;
	}
	
	@Basic
	public double getY() {
		return y;
	}
	
	/**
	 * Returns the norm of this vector
	 * @return	the norm of this vector
	 * 			| sqrt(this.getX()^2+this.getY()^2)
	 */
	public double norm() {
		return Math.sqrt(Math.pow(this.getX(),2)+Math.pow(this.getY(), 2));
	}
	
	/**
	 * Calculate the scalar product of this vector with another vector
	 * @param vector
	 * @return	the scalar product of this vector and the given vector
	 * 			| vector.getX()*this.getX()+vector.getY()*this.getY()
	 */
	public double scalarProduct(Vector vector) {
		return (vector.getX()*this.getX()+vector.getY()*this.getY());
	}
	
	/**
	 * Returns the distance between to vectors
	 * 
	 * @param vector
	 * @return	the distance between this vector and another vector
	 * 			| sqrt((vector.getX()-this.getX())^2+(vector.getY()-this.getY())^2)
	 */
	public double getDistanceBetween(Vector vector) {
		double x1 = this.getX();
		double x2 = vector.getX();
		double y1 = this.getY();
		double y2 = vector.getY();
		return Math.sqrt(Math.pow((x2-x1), 2)+Math.pow((y2-y1), 2));
		
	}
	
	/**
	 * Returns the subtraction between the components of this vector and a given vector
	 * @param vector
	 * @return	a vector with x-value of the difference between this x-value and the x-value of the given vector
	 * 				and with y-value the difference between this y-value and the y-value of the given vector.
	 */
	public Vector delta(Vector vector) {
		double x = (this.getX() - vector.getX());
		double y = (this.getY() - vector.getY());
		Vector returnVector = new Vector(x,y);
		//returnVector.setX(x);
		//returnVector.setY(y);
		return returnVector;
	}
	
	/**
	 * Returns if it is possible to sum the given vectors
	 * @param vector1
	 * @param vector2
	 * @return	true if it is possible to sum the given vectors
	 * 			| result == (isValidComponentSum(vector1.getX(),vector2.getX()) 
				|				&& isValidComponentSum(vector1.getY(),vector2.getY()))
	 */
	public static boolean isValidVectorSum(Vector vector1, Vector vector2) {
		if(isValidComponentSum(vector1.getX(),vector2.getX()) 
				&& isValidComponentSum(vector1.getY(),vector2.getY())) {
			return true;
		}
		else {
			return false;
		}
	}
	
	/**
	 * Checks wether it is possible to sum the given doubles
	 * @param a
	 * @param b
	 * @return	true if it is possible to sum the given doubles
	 * 			| result == !(a+b == Double.POSITIVE_INFINITY || a+b == Double.NEGATIVE_INFINITY)
	 */
	private static boolean isValidComponentSum(double a, double b) {
		if(a+b == Double.POSITIVE_INFINITY || a+b == Double.NEGATIVE_INFINITY)
			return false;
		return true;
	}
	
	/**
	 * Returns whether the two given vectors are subtractable
	 * @param vector1
	 * @param vector2
	 * @return	true if it is possible to subtract the two given vectors
	 * 			| result == (isValidComponentSubtraction(vector1.getX(),vector2.getX()) 
				|				&& isValidComponentSubtraction(vector1.getY(),vector2.getY()))
	 */
	public static boolean isValidVectorSubtraction(Vector vector1, Vector vector2) {
		if(isValidComponentSubtraction(vector1.getX(),vector2.getX()) 
				&& isValidComponentSubtraction(vector1.getY(),vector2.getY())) {
			return true;
		}
		else {
			return false;
		}
			
	}
	
	/**
	 * checks wether it is possible to subtract the two given doubles
	 * @param a
	 * @param b
	 * @return	true if the given doubles are subtractable
	 * 			|result == !(a-b == Double.POSITIVE_INFINITY || a-b == Double.NEGATIVE_INFINITY)
	 */
	private static boolean isValidComponentSubtraction(double a, double b) {
		if(a-b == Double.POSITIVE_INFINITY || a-b == Double.NEGATIVE_INFINITY)
			return false;
		return true;
	}
	
	@Override
	public boolean equals(Object other) {
		if(other == null) {
			return false;
		}
		if(this.getClass() != other.getClass()) {
			return false;
		}
		Vector otherVector = (Vector) other;
		return (Util.fuzzyEquals(otherVector.getX(), this.getX()) && Util.fuzzyEquals(otherVector.getY(), this.getY()));
	}
	
	@Override
	public String toString() {
		return ("x: " + this.getX() + "," + "y: " + this.getY());
	}

}
